package com.xiaoyu.lanling.feature.im.provider

import `in`.srain.cube.concurrent.AppThreads
import `in`.srain.cube.request.JsonData
import `in`.srain.cube.util.internal.AppConsumer2
import android.text.TextUtils
import com.xiaoyu.base.AppDatabase
import com.xiaoyu.base.DBCall
import com.xiaoyu.base.app.AppContext
import com.xiaoyu.base.data.UserData
import com.xiaoyu.base.data.UserInfoDataProvider
import com.xiaoyu.im.ChatToken
import com.xiaoyu.im.datamodel.AppMessage
import com.xiaoyu.im.datamodel.MessagePayload
import com.xiaoyu.im.provider.AbstractMessageDataProvider
import com.xiaoyu.im.request.MessageRequest
import com.xiaoyu.lanling.R
import com.xiaoyu.lanling.common.Constant.MessageAttrsKey.GIFT
import com.xiaoyu.lanling.event.gift.ReceiveGiftEvent
import com.xiaoyu.lanling.feature.chat.data.MessageListData
import com.xiaoyu.lanling.feature.chat.model.message.MessageType

class MessageDataProvider private constructor() : AbstractMessageDataProvider() {

    init {
        mOnMessageSentFunction = AppConsumer2<AppMessage, AppMessage> { pendingMessage: AppMessage, successMessage: AppMessage -> MessageListData.instance.onMessageReplace(pendingMessage, successMessage) }
    }

    fun addAdminMessageLocally(chatId: String?, text: String?, color: String?, action: String?) {
        val payload = MessagePayload.obtain(MessageType.TYPE_01_SYSTEM)
        payload.text = text
        payload.putAttrs("color", color)
        payload.putAttrs("action", action)
        val message = AppMessage.create(ChatToken.forChatId(chatId), payload)
        val entity = message.toEntity()
        DBCall.run { database: AppDatabase -> database.messageDao().upsert(entity) }
        MessageListData.instance.onNewMessageLoad(message)
    }

    override fun onMessageRecall(message: AppMessage) {
        super.onMessageRecall(message)
        UserInfoDataProvider.getInstance().ensureUser(message.senderUid)
        val sender = UserInfoDataProvider.getInstance().fetchFromMemory(message.senderUid)
        val fromDesc = if (UserData.getInstance().isSelf(message.senderUid)) "你" else if (!TextUtils.isEmpty(sender.remark)) sender.remark else message.senderUid
        val recallText = fromDesc + AppContext.getString(R.string.chat_message_recall)
        message.payload.recall(MessageType.TYPE_01_SYSTEM, recallText, message.payload.text)
        val entity = message.toEntity()
        DBCall.run { database: AppDatabase -> database.messageDao().upsert(entity) }
        MessageListData.instance.onMessageUpdate(AppMessage.fromEntity(entity))
    }

    override fun onMessageFail(request: MessageRequest) {
        super.onMessageFail(request)
        MessageListData.instance.onMessageUpdate(request.pendingMessage)
    }

    override fun onMessageReceived(message: AppMessage) {
        super.onMessageReceived(message)
        if (message.payload.messageType == MessageType.TYPE_1003_GIFT) {
            onReceiveGift(message)
        }
        MessageListData.instance.onNewMessageLoad(message)
    }

    override fun processEventLogForReceiveMessage(message: AppMessage, conversationType: String, conversationName: String) {
        if (message.payload.messageType == MessageType.TYPE_02_SERVER_PUSH) {
            return
        }
        super.processEventLogForReceiveMessage(message, conversationType, conversationName)
    }

    override fun deleteMessage(message: AppMessage) {
        super.deleteMessage(message)
        MessageListData.instance.onMessageRemove(message)
    }

    override fun onMessageNewTipUpdate(message: AppMessage) {
        super.onMessageNewTipUpdate(message)
        MessageListData.instance.setReadNewTip(message)
    }

    override fun onReceiveAudioMessagePlayCompleteAsync(message: AppMessage) {
        AppThreads.runOnIOThread { MessageListData.instance.onReceiveAudioMessagePlayComplete(message) }
    }

    override fun preparePendingMessage(request: MessageRequest) {
        super.preparePendingMessage(request)
        val pendingMessage = request.pendingMessage
        if (request.isResend) {
            MessageListData.instance.onMessageUpdate(pendingMessage)
        } else {
            MessageListData.instance.onNewMessageLoad(pendingMessage)
        }
    }

    private fun onReceiveGift(message: AppMessage) {
        val attrs: JsonData = message.payload.attrsCopy
        val fromUid = message.senderUid
        ReceiveGiftEvent(fromUid, attrs.optJson(GIFT)).post()
    }

    companion object {
        val instance = MessageDataProvider()
    }
}